import { takeLatest, call, put, throttle } from 'redux-saga/effects';
import R from 'ramda';
import api from '../api.js';
import {
    FETCH_ME_BEGIN,
    FETCH_ME_SUCCESS,
    FETCH_ME_FAILED,
    CREATE_USER_BEGIN,
    CREATE_USER_SUCCESS,
    CREATE_USER_FAILED,
    FETCH_THREAD_LIST_BEGIN,
    FETCH_THREAD_LIST_SUCCESS,
    FETCH_THREAD_LIST_FAILED,
    FETCH_THREAD_BEGIN,
    FETCH_THREAD_SUCCESS,
    FETCH_THREAD_FAILED,
    FETCH_COMMENTS_BEGIN,
    FETCH_COMMENTS_SUCCESS,
    FETCH_COMMENTS_FAILED,
    CREATE_COMMENTS_BEGIN,
    CREATE_COMMENTS_FAILED,
    CREATE_COMMENTS_SUCCESS,
    CREATE_THREAD_BEGIN,
    CREATE_THREAD_SUCCESS,
    CREATE_THREAD_FAILED,
    LOGIN_BEGIN,
    LOGIN_SUCCESS,
    LOGIN_FAILED
} from '../actions';
import axios from 'axios';

function get (url, params) {
    return axios({
        url,
        params,
        method: 'get'
    }).then(R.prop('data'))
}
function post (url, params) {
    return axios.post(url, params).then(R.prop('data'))
}
function createFetch(config) {
    return function* ({payload}){
        const parseConfig = (config.parse || R.identity)(config, payload)
        const [begin, success, failed] = parseConfig.types
        const api = parseConfig.api;
        try{
            yield put({type: success, response: yield call(get, api)})
        }catch (e) {
            yield put({type: failed, error: e})
        }
    }
}
function createPost(config) {
    return function * ({payload}) {
        const newConfig = (config.parse || R.identity)(config, payload)
        const [begin, success, failed ] = newConfig.types;
        const api = newConfig.api;
        try{
            const response = yield call(post, api, payload)
            yield put({type: success, response})
        }catch(e) {
            console.log(e)
            yield put({type: failed, error: e})
        }
    }
}

export default function* () {
    yield* [
        takeLatest(LOGIN_BEGIN, createPost({
            types: [
                LOGIN_BEGIN,
                LOGIN_SUCCESS,
                LOGIN_FAILED
            ],
            api: api.LOGIN
        })),
        takeLatest(CREATE_THREAD_BEGIN, createPost({
            types: [
                CREATE_THREAD_BEGIN,
                CREATE_THREAD_SUCCESS,
                CREATE_THREAD_FAILED
            ],
            api: api.THREAD
        })),
        takeLatest(CREATE_COMMENTS_BEGIN, createPost({
            types: [
                CREATE_COMMENTS_BEGIN,
                CREATE_COMMENTS_SUCCESS,
                CREATE_COMMENTS_FAILED
            ],
            api: api.COMMENT,
            parse: (config, payload) => ({...config, api: R.replace(':id', payload.id, api.COMMENT)})
        })),
        takeLatest(FETCH_COMMENTS_BEGIN, createFetch({
            types: [
                FETCH_COMMENTS_BEGIN,
                FETCH_COMMENTS_SUCCESS,
                FETCH_COMMENTS_FAILED
            ],
            api: api.COMMENT,
            parse: (config, payload) => ({...config, api: R.replace(':id', payload.id, api.COMMENT)})
        })),
        takeLatest(FETCH_THREAD_BEGIN, createFetch({
            types: [
                FETCH_THREAD_BEGIN,
                FETCH_THREAD_SUCCESS,
                FETCH_THREAD_FAILED
            ],
            api: api.SPECIALTHREAD,
            parse: (config, payload) => ({...config, api: R.replace(':id', payload.id, config.api)})
        })),
        takeLatest(FETCH_THREAD_LIST_BEGIN, createFetch({
            types: [
                FETCH_THREAD_LIST_BEGIN,
                FETCH_THREAD_LIST_SUCCESS,
                FETCH_THREAD_LIST_FAILED
            ],
            api: api.THREAD
        })),
        takeLatest(FETCH_ME_BEGIN, createFetch({
            types: [
                FETCH_ME_BEGIN,
                FETCH_ME_SUCCESS,
                FETCH_ME_FAILED
            ],
            api: api.ME
        })),
        takeLatest(CREATE_USER_BEGIN, createPost({
            types: [
                CREATE_USER_BEGIN,
                CREATE_USER_SUCCESS,
                CREATE_USER_FAILED
            ],
            api: api.USER
        }))
    ]
}
